Skip to content

Conversation

gpaucot
Copy link

@gpaucot gpaucot commented Sep 17, 2024

Switching to native federation I noticed the strategy did not take into account the singleton and requiredVersion yet.
Here is an implementation with JSDoc & UT.

I also tested it locally with 4 angular workspaces, at the image of what we use in my company:

  • v18.2.4 workspace with a shell and a mfe using a core library (sharedMapping).
  • v17 workspace intended to represent another team's work with a MFE using the core from the shell. This allows me to verify that an older major works (required version >=17.0.0)
  • v18.2.3 workspace intended to represent another team's work with a MFE using the core from the shell. This allows me to verify that a v18 but slightly behind works (required version ^18.0.0) and load it during initFederation or later on routing with loadRemoteModule.

@manfredsteyer I hope this does not diverge from the path you are willing to take for the future 🙂 If you find a little time to make a feedback I would be very grateful

Cheers,
Gaëtan

@okamiconcept
Copy link

I'm very surprised that this core base feature (semantic versioning between shell and remote) is not yet in the Native Federation package since it's the main feature of Module Federation...

For the moment the library is just usable if you have the same packages versions in the host and the remote, especially for the Angular version, if the remote have the version 18.1.0 and the shell 18.1.1 there will be 2 different angular framework loaded, each one with it's own injector, so they can't communicate with each other.

@manfredsteyer do you use it already in production?

FYI i've created a patch in the meantime (with an other approach, simpler: #399 (comment))

@rainerhahnekamp
Copy link
Collaborator

@gpaucot @okamiconcept. The problem is that Angular - once compiled - doesn't provide compatibility between patch levels. So if we would allow to merge multiple Angular versions together, you might run into some serious issues.

It is the same with module federation btw.

The question is if we want to still allow it (with a big warning message "at your own risk").

You can also checkout this video stream where Minko Gechev explains the problem: https://youtu.be/oQbLkcws_pQ?si=IFntfQ0k0HvSHx26&t=2271 (Time Position: 37:51)

The alternative would be to combine NF/MF with Web Components, aka. Frankenstein solution.

@okamiconcept
Copy link

@rainerhahnekamp Yes you are totally right, there is a chance of incompatibility, but there is still a possibility of specifying the compatibility of the versions between them by using specific semantic versioning in the package.json or by specifying directly in the federation.config.js

There is always a upgrading strategy between master / remotes to be sure there is no incompatibility, with some regression tests, to ensure there is a compatibility between patch / minor / major versions a least :)

The problem here is that we cannot mimic the basic Module Federation implementation for now, so there is no chance of letting us decide if we take the risk of accepting compatibility between 2 versions of Angular (or any other library).

@rainerhahnekamp rainerhahnekamp self-requested a review October 22, 2024 21:14
@Nxtivision
Copy link

Any news of this? Because we have the same problem inside our company 😁

@manfredsteyer manfredsteyer force-pushed the main branch 4 times, most recently from 93c1fc5 to 18c2874 Compare January 12, 2025 19:32
@rribeiro93k
Copy link

@rainerhahnekamp based on @okamiconcept last comment, It will be some update about this case? I also understand
about Angular incompatibility for some different versions, but It shouldn't configurable? for my understanding in native-federation the params requiredVersion and singleton isn't used in fact. This could be a problem for intern libraries, because I need to keep the same version for shell and all remotes to not create multiple instances for singleton services for example

@rainerhahnekamp
Copy link
Collaborator

@rribeiro93k, the only thing that you can configure is that you are getting an error on version mismatch. as soon as the angular version of a remote doesn't match the one of the host, you face that risk. you have to remember that from Angular's perspective you give it a lazy loaded module and Angular expects the compiled one to be compliant with that one of the host.

it is not just about sharing.

@ng-sp7
Copy link

ng-sp7 commented Jun 29, 2025

Hi @gpaucot 👋,

Thanks for this contribution — it adds functionality that would really help in our project.

Just wondering if there's any plan or timeline for merging this? We’re currently waiting on it to proceed with part of our implementation.

Appreciate your work and looking forward to this getting merged!

@pburgmer
Copy link

pburgmer commented Jul 9, 2025

I would also need a solution or at least the option to configure it and then test the compatibility manually. At the moment we have to release the whole stack as soon as a any library releases a new version.

Our situation:
angular -> low-level-library -> high-level-library -> apps

@bh3605
Copy link

bh3605 commented Jul 16, 2025

@pburgmer There's this "vanilla" library that does do version semantics. https://github.com/topicusonderwijs/vanilla-native-federation

@Aukevanoost
Copy link

Aukevanoost commented Jul 23, 2025

@gpaucot @okamiconcept. The problem is that Angular - once compiled - doesn't provide compatibility between patch levels. So if we would allow to merge multiple Angular versions together, you might run into some serious issues.

@rainerhahnekamp I watched the video and understand the risk. Would it make sense to build a setting in the native federation that when shareAll is used, all Angular related packages ((pkg) => pkg.startsWith('@angular')) are set to singleton: false by default? This way it is still possible to share packages but allow a more conservative approach by default for Angular related packages.

Or even allow an extra option sharingStrategy: "strict"|"range" or shareScope: "strict" that provides the functionality that is now implemented for externals when "strict" and chooses the most compatible version when "range" is selected.

@Ketec
Copy link

Ketec commented Sep 17, 2025

This is a quite problematic with npm packages. Ensuring perfect 1:1 sync across many teams and remotes + common npm library is effectively unrealistic.

Especially with internal library updates - the moment shell is updated, every module breaks until they release an update. Because it creates a new scope, no services, providers etc. are initialized.

Chances are that minor/patch updates are compatible and internal libraries are built to be backwards compatible too.
And at worst, a model that is too out of date would fail, as opposed to everything.

Even if risky, can there be a potential flag to enforce using same packages from shell - even ignoring the version (or just warning). Or requiredVersion = any.

Or can we potentially make it consider npm package as sharedMappings instead (and map it from node_modules instead of local dir)?

I did scan through the source, but not familiar with it so i can't easily track down where the version comparison/detection happens.

@Ketec
Copy link

Ketec commented Sep 17, 2025

A bit digging and i guess the culprit is this util.
the globalCache holds packages and the key is name + exact version.
So it clearly never works if even version range is specified.
image

import { SharedInfo } from './federation-info';
import { globalCache } from './global-cache';

const externals = globalCache.externals;

function getExternalKey(shared: SharedInfo) {
  return `${shared.packageName}@${shared.version}`;
}

export function getExternalUrl(shared: SharedInfo): string | undefined {
  const packageKey = getExternalKey(shared);
console.log(externals, packageKey);
  return externals.get(packageKey);
}

export function setExternalUrl(shared: SharedInfo, url: string): void {
  const packageKey = getExternalKey(shared);
  externals.set(packageKey, url);
}

@Aukevanoost
Copy link

@Ketec you are correct! As also stated here: #844 (comment)

@Ketec
Copy link

Ketec commented Sep 17, 2025

At this point, i'll just use a local clone of the entire lib just to override it to

function getExternalKey(shared: SharedInfo) {
  if (shared.singleton) {
    return `${shared.packageName}`;
  }else {
    return `${shared.packageName}@${shared.version}`;
  }
}

As i do not how long any fix or full accepted solution may get added.
If any remote uses incompatible versions - then they are the ones breaking, but at least it's not an automatic failure.
The compatibility responsibility will remain with the remote, but it's not an automatic fail.

Having multiple versions of anything running in the same page without full isolation is going to cause problems anyways (shared global, cookies, cache etc).

And Secure ECMAScript is still not outside draft (needs shim) - this might provide the full isolated compartments needed for true multi version native federation.

@bh3605
Copy link

bh3605 commented Sep 19, 2025

@Ketec This library did add the capability to respect patch versions of angular when it does the dependency detection (or whatever it's called).
https://github.com/topicusonderwijs/vanilla-native-federation

@Ketec
Copy link

Ketec commented Sep 19, 2025

Yes, but mixing up and using forks of libraries is not generallya good idea in the enterprise environment.
I can just keep a copy of the lib for nf runtime locally for the shell init.

Wanted to just build a modified package, but nx did not behave (postinstall scripts and build just froze and stopped progressing).

@Aukevanoost
Copy link

@Ketec I understand you! And this is suboptimal, but the abovementioned library is not a fork but currently an extension. You can easily replace the default runtime in the host with this one until the official one supports sharing deps (check https://github.com/aukevanoost/native-federation-examples-ng/). It has some docs so you can check if it serves your use case.

Please do note that your current setup with alterations will break if one of your micro frontends/host rocks an incompatible dependency. It will be roulette if your micro frontend will fail or not, depending on which micro frontend/host loads first.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants